#include "Entity3D.h"


Entity3D::Entity3D()
{
	position = D3DXVECTOR3(0,0,0);
	angle = D3DXVECTOR3(0,0,0);
	scale = D3DXVECTOR3(0,0,0);
	speed = D3DXVECTOR3(0,0,0);
	acceleration = D3DXVECTOR3(0,0,0);
	isActive = true;
	meshInfo = NULL;
	c=0;
	add = 1;
}
Entity3D::Entity3D(D3DXVECTOR3 _position,D3DXVECTOR3 _angle,D3DXVECTOR3 _scale,D3DXVECTOR3 _speed,D3DXVECTOR3 _acceleration,bool _isActive,MeshInfo * _mesh)
{
	position = _position;
	angle = _angle;
	speed = _speed;
	scale = _scale;
	acceleration = _acceleration;
	isActive = _isActive;
	meshInfo = _mesh;
}
void Entity3D::calculateBoundingBox()
{
	D3DXVECTOR3 min;
	D3DXVECTOR3 max;
	LPDIRECT3DVERTEXBUFFER9 v_buffer;
	meshInfo->mesh->GetVertexBuffer(&v_buffer);
	void *pVoid;
	v_buffer->Lock(0,0,(void**)&pVoid,0);
	v_buffer->Unlock();
	if(meshInfo!=NULL)
	{
		D3DXComputeBoundingBox((D3DXVECTOR3 *)pVoid,meshInfo->mesh->GetNumVertices(),meshInfo->mesh->GetNumBytesPerVertex(),&min,&max);
	}
	boundingBox.x=abs(max.x-min.x)*(scale.x)/2;
	boundingBox.y=abs(max.y-min.y)*(scale.y)/2;
	boundingBox.z=abs(max.z-min.z)*(scale.z)/2;
}
D3DXVECTOR3 Entity3D::getBoundingBox()
{
	return boundingBox;
}
void Entity3D::setAcceleration(D3DXVECTOR3 _acceleration)
{
	acceleration = _acceleration;
}
void Entity3D::setAngle(D3DXVECTOR3 _angle)
{
	angle = _angle;
}
void Entity3D::setIsActive(bool _isActive)
{
	isActive = _isActive;
}
void Entity3D::setMesh(MeshInfo *_mesh)
{
	meshInfo = _mesh;
}
void Entity3D::setPosition(D3DXVECTOR3 _position)
{
	position = _position;
}
void Entity3D::setScale(D3DXVECTOR3 _scale)
{
	scale = _scale;
}
void Entity3D::setSpeed(D3DXVECTOR3 _speed)
{
	speed = _speed;
}
D3DXVECTOR3 Entity3D::getAcceleration()
{
	return acceleration;
}
D3DXVECTOR3 Entity3D::getAngle()
{
	return angle;
}
D3DXVECTOR3 Entity3D::getForward()
{
	D3DXVECTOR3 virtualForward(0,0,-1);
	D3DXMATRIX matRotate;
	D3DXMatrixRotationYawPitchRoll(&matRotate,D3DXToRadian(angle.y),D3DXToRadian(angle.x),D3DXToRadian(angle.z));

	D3DXVECTOR4 v4rotation;
	D3DXVec3Transform(&v4rotation,&virtualForward,&matRotate);
	
	forward = (D3DXVECTOR3)v4rotation;
	return forward;
}
D3DXVECTOR3 Entity3D::getUp()
{
	return up;
}
bool Entity3D::getIsActive()
{
	return isActive;
}
MeshInfo * Entity3D::getMesh()
{
	return meshInfo;
}
D3DXVECTOR3 Entity3D::getPosition()
{
	return position;
}
D3DXVECTOR3 Entity3D::getScale()
{
	return scale;
}
D3DXVECTOR3 Entity3D::getSpeed()
{
	return speed;
}
void Entity3D::Update(DWORD dt)
{
	speed += acceleration * (dt/100.0f);
	position += speed * (dt/100.0f);
	if((c>3.14f)||(c<0))
	{
		add*=-1;
	}
	c+=0.03*add;
}
void Entity3D::Draw(LPDIRECT3DDEVICE9 _d3ddev,bool _light)
{
	D3DXVECTOR3 virtualUp(0,1,0);
	
	D3DXMATRIX matTranslate;
	D3DXMATRIX matScale;
	D3DXMATRIX matRotate;
	D3DXMatrixTranslation(&matTranslate,position.x,position.y,position.z);
	D3DXMatrixScaling(&matScale,scale.x,scale.y,scale.z);
	D3DXMatrixRotationYawPitchRoll(&matRotate,D3DXToRadian(angle.y),D3DXToRadian(angle.x),D3DXToRadian(angle.z));
	

	D3DXVECTOR4 v4rotationUp;
	D3DXVec3Transform(&v4rotationUp,&virtualUp,&matRotate);

	up = (D3DXVECTOR3)v4rotationUp;

	D3DXMATRIX mvpMatrix;
	mvpMatrix._11 = 0;
	mvpMatrix._12 = 0;
	mvpMatrix._13 = 0;
	mvpMatrix._14 = 0;
	mvpMatrix._21 = 0;
	mvpMatrix._22 = 0;
	mvpMatrix._23 = 0;
	mvpMatrix._24 = 0;
	mvpMatrix._31 = 0;
	mvpMatrix._32 = 0;
	mvpMatrix._33 = 0;
	mvpMatrix._34 = 0;
	mvpMatrix._41 = 0;
	mvpMatrix._42 = 0;
	mvpMatrix._43 = 0;
	mvpMatrix._44 = 0;



	_d3ddev->SetTransform(D3DTS_WORLD,&(matRotate*matScale*matTranslate));
	//_d3ddev->SetTransform(D3DTS_WORLD,&mvpMatrix);
	
	D3DXMATRIX world;
	D3DXMATRIX view;
	D3DXMATRIX projection;
	_d3ddev->GetTransform(D3DTS_WORLD,&world);
	_d3ddev->GetTransform(D3DTS_VIEW,&view);
	_d3ddev->GetTransform(D3DTS_PROJECTION,&projection);

	
	float * model = new float[16];
	model[0] = world._11;
	model[1] = world._12;
	model[2] = world._13;
	model[3] = world._14;
	model[4] = world._21;
	model[5] = world._22;
	model[6] = world._23;
	model[7] = world._24;
	model[8] = world._31;
	model[9] = world._32;
	model[10] = world._33;
	model[11] = world._34;
	model[12] = world._41;
	model[13] = world._42;
	model[14] = world._43;
	model[15] = world._44;

	mvpMatrix = world*view*projection;

	float * mat = new float[16];
	mat[0] = mvpMatrix._11;
	mat[1] = mvpMatrix._12;
	mat[2] = mvpMatrix._13;
	mat[3] = mvpMatrix._14;
	mat[4] = mvpMatrix._21;
	mat[5] = mvpMatrix._22;
	mat[6] = mvpMatrix._23;
	mat[7] = mvpMatrix._24;
	mat[8] = mvpMatrix._31;
	mat[9] = mvpMatrix._32;
	mat[10] = mvpMatrix._33;
	mat[11] = mvpMatrix._34;
	mat[12] = mvpMatrix._41;
	mat[13] = mvpMatrix._42;
	mat[14] = mvpMatrix._43;
	mat[15] = mvpMatrix._44;
	
	cgSetMatrixParameterfc(modelWorld,world);
	CGerror error;
	error = cgGetError();
	cgSetMatrixParameterfc(mvp,mat);
	error = cgGetError();
	const char* errorString2 = cgGetErrorString(error);
	cgUpdateProgramParameters(program);

	
	for(DWORD i=0;i<meshInfo->numMaterials;i++)
	{
		//setear el material y la textura para este subgrupo
		_d3ddev->SetMaterial(&meshInfo->meshMaterials[i]);
		_d3ddev->SetTexture(0,meshInfo->meshTextures[i]);
		if(!_light)
		{
			//cgD3D9SetTexture(normalTexture,meshInfo->meshTextures[i]);  
			//cgUpdateProgramParameters(programFragment);
			cgD3D9SetTexture(dispersionDecalTexture,meshInfo->meshTextures[i]);  
			cgD3D9SetTexture(skyBoxDispersionTexture,pSkyboxTexture); 
			cgUpdateProgramParameters(dispersionProgram);
		}
		else
		{
			cgD3D9SetTexture(lightSourceTexture,meshInfo->meshTextures[i]);  
			cgUpdateProgramParameters(lightSourceProgram);
		}
		//dibujar el subgrupo
		meshInfo->mesh->DrawSubset(i);
	}
}

void Entity3D::Draw(LPDIRECT3DDEVICE9 _d3ddev,LPDIRECT3DVERTEXBUFFER9 _v_buffer,LPDIRECT3DINDEXBUFFER9 _i_buffer,int _cantVertex,int _cantPrimitives)
{
	D3DXVECTOR3 virtualForward(0,0,-1);
	D3DXVECTOR3 virtualUp(0,1,0);

	D3DXMATRIX matTranslate;
	D3DXMATRIX matScale;
	D3DXMATRIX matRotate;
	D3DXMatrixTranslation(&matTranslate,position.x,position.y,position.z);
	D3DXMatrixScaling(&matScale,scale.x,scale.y,scale.z);
	D3DXMatrixRotationYawPitchRoll(&matRotate,D3DXToRadian(angle.y),D3DXToRadian(angle.x),D3DXToRadian(angle.z));

	D3DXVECTOR4 v4rotation;
	D3DXVec3Transform(&v4rotation,&virtualForward,&matRotate);
	
	forward = (D3DXVECTOR3)v4rotation;

	D3DXVECTOR4 v4rotationUp;
	D3DXVec3Transform(&v4rotationUp,&virtualUp,&matRotate);

	up = (D3DXVECTOR3)v4rotationUp;

	D3DXMATRIX mvpMatrix;
	mvpMatrix._11 = 0;
	mvpMatrix._12 = 0;
	mvpMatrix._13 = 0;
	mvpMatrix._14 = 0;
	mvpMatrix._21 = 0;
	mvpMatrix._22 = 0;
	mvpMatrix._23 = 0;
	mvpMatrix._24 = 0;
	mvpMatrix._31 = 0;
	mvpMatrix._32 = 0;
	mvpMatrix._33 = 0;
	mvpMatrix._34 = 0;
	mvpMatrix._41 = 0;
	mvpMatrix._42 = 0;
	mvpMatrix._43 = 0;
	mvpMatrix._44 = 0;



	_d3ddev->SetTransform(D3DTS_WORLD,&(matRotate*matScale*matTranslate));
	//_d3ddev->SetTransform(D3DTS_WORLD,&mvpMatrix);
	
	D3DXMATRIX world;
	D3DXMATRIX view;
	D3DXMATRIX projection;
	_d3ddev->GetTransform(D3DTS_WORLD,&world);
	_d3ddev->GetTransform(D3DTS_VIEW,&view);
	_d3ddev->GetTransform(D3DTS_PROJECTION,&projection);

	//mvpMatrix = projection*view*world;
	mvpMatrix = world*view*projection;

	float * mat = new float[16];
	mat[0] = mvpMatrix._11;
	mat[1] = mvpMatrix._12;
	mat[2] = mvpMatrix._13;
	mat[3] = mvpMatrix._14;
	mat[4] = mvpMatrix._21;
	mat[5] = mvpMatrix._22;
	mat[6] = mvpMatrix._23;
	mat[7] = mvpMatrix._24;
	mat[8] = mvpMatrix._31;
	mat[9] = mvpMatrix._32;
	mat[10] = mvpMatrix._33;
	mat[11] = mvpMatrix._34;
	mat[12] = mvpMatrix._41;
	mat[13] = mvpMatrix._42;
	mat[14] = mvpMatrix._43;
	mat[15] = mvpMatrix._44;

	
	CGerror error;
	error = cgGetError();
	cgSetMatrixParameterfc(mvp,mat);
	error = cgGetError();
	const char* errorString2 = cgGetErrorString(error);
	cgUpdateProgramParameters(program);

	D3DMATERIAL9 material;
	ZeroMemory(&material,sizeof(D3DMATERIAL9));
	material.Diffuse = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
	material.Ambient = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
	
	LPDIRECT3DTEXTURE9 texture;
	ZeroMemory(&texture,sizeof(LPDIRECT3DTEXTURE9));

	_d3ddev->SetFVF(CUSTOMFVF);
	_d3ddev->SetStreamSource(0,_v_buffer,0,sizeof(CUSTOMVERTEX));
	_d3ddev->SetIndices(_i_buffer);
	_d3ddev->SetMaterial(&material);
	_d3ddev->SetTexture(0,texture);
	_d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,_cantVertex,0,_cantPrimitives);
}

void Entity3D::Draw(LPDIRECT3DDEVICE9 _d3ddev,LPDIRECT3DVERTEXBUFFER9 _v_buffer,LPDIRECT3DINDEXBUFFER9 _i_buffer)
{
	D3DXVECTOR3 virtualForward(0,0,-1);
	D3DXVECTOR3 virtualUp(0,1,0);

	D3DXMATRIX matTranslate;
	D3DXMATRIX matScale;
	D3DXMATRIX matRotate;
	D3DXMatrixTranslation(&matTranslate,position.x,position.y,position.z);
	D3DXMatrixScaling(&matScale,scale.x,scale.y,scale.z);
	D3DXMatrixRotationYawPitchRoll(&matRotate,D3DXToRadian(angle.y),D3DXToRadian(angle.x),D3DXToRadian(angle.z));

	D3DXVECTOR4 v4rotation;
	D3DXVec3Transform(&v4rotation,&virtualForward,&matRotate);
	
	forward = (D3DXVECTOR3)v4rotation;

	D3DXVECTOR4 v4rotationUp;
	D3DXVec3Transform(&v4rotationUp,&virtualUp,&matRotate);

	up = (D3DXVECTOR3)v4rotationUp;

	D3DXMATRIX mvpMatrix;
	mvpMatrix._11 = 0;
	mvpMatrix._12 = 0;
	mvpMatrix._13 = 0;
	mvpMatrix._14 = 0;
	mvpMatrix._21 = 0;
	mvpMatrix._22 = 0;
	mvpMatrix._23 = 0;
	mvpMatrix._24 = 0;
	mvpMatrix._31 = 0;
	mvpMatrix._32 = 0;
	mvpMatrix._33 = 0;
	mvpMatrix._34 = 0;
	mvpMatrix._41 = 0;
	mvpMatrix._42 = 0;
	mvpMatrix._43 = 0;
	mvpMatrix._44 = 0;



	_d3ddev->SetTransform(D3DTS_WORLD,&(matRotate*matScale*matTranslate));
	//_d3ddev->SetTransform(D3DTS_WORLD,&mvpMatrix);
	
	D3DXMATRIX world;
	D3DXMATRIX view;
	D3DXMATRIX projection;

	D3DXMatrixOrthoLH(&projection,1024,768,0.3f,1000.0f);
	D3DXMatrixIdentity(&view);
	_d3ddev->GetTransform(D3DTS_WORLD,&world);
	//_d3ddev->GetTransform(D3DTS_VIEW,&view);
	//_d3ddev->GetTransform(D3DTS_PROJECTION,&projection);

	//mvpMatrix = projection*view*world;
	mvpMatrix = world*projection;

	float * mat = new float[16];
	mat[0] = mvpMatrix._11;
	mat[1] = mvpMatrix._12;
	mat[2] = mvpMatrix._13;
	mat[3] = mvpMatrix._14;
	mat[4] = mvpMatrix._21;
	mat[5] = mvpMatrix._22;
	mat[6] = mvpMatrix._23;
	mat[7] = mvpMatrix._24;
	mat[8] = mvpMatrix._31;
	mat[9] = mvpMatrix._32;
	mat[10] = mvpMatrix._33;
	mat[11] = mvpMatrix._34;
	mat[12] = mvpMatrix._41;
	mat[13] = mvpMatrix._42;
	mat[14] = mvpMatrix._43;
	mat[15] = mvpMatrix._44;

	cgSetMatrixParameterfc(mvp,mat);
	CGerror error;
	error = cgGetError();
	cgUpdateProgramParameters(program);

	const char* errorString2 = cgGetErrorString(error);

	_d3ddev->SetFVF(CUSTOMFVF);
	_d3ddev->SetStreamSource(0,_v_buffer,0,sizeof(CUSTOMVERTEX));
	_d3ddev->SetIndices(_i_buffer);
	_d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);
}


bool Entity3D::CheckCollision(Entity3D * _collisionObject)
{
	if(((boundingBox.x+_collisionObject->getBoundingBox().x)>(abs(position.x-_collisionObject->getPosition().x)))&&
		((boundingBox.y+_collisionObject->getBoundingBox().y)>(abs(position.y-_collisionObject->getPosition().y)))&&
		((boundingBox.z+_collisionObject->getBoundingBox().z)>(abs(position.z-_collisionObject->getPosition().z))))
	{
		return true;
	}
	else
		return false;
}
D3DXVECTOR3 Entity3D::lookAt(D3DXVECTOR3 _lookAtPosition)
{
	D3DXVECTOR3 newRotation;
	newRotation.y = D3DXToDegree(atan2(_lookAtPosition.z,sqrt((_lookAtPosition.x*_lookAtPosition.x)+(_lookAtPosition.y*_lookAtPosition.y))));
	newRotation.z = D3DXToDegree(atan2(_lookAtPosition.y,_lookAtPosition.x));
	newRotation.x = 0;
	return newRotation;
}
